A network storage controller is a processing system that is used to store and retrieve data on behalf of one or more hosts on a network. A storage server is a type of storage controller that operates on behalf of one or more clients on a network, to store and manage data in a set of mass storage devices, such as magnetic or optical storage-based disks or tapes. Some storage servers are designed to service file-level requests from hosts, as is commonly the case with file servers used in a network attached storage (NAS) environment. Other storage servers are designed to service block-level requests from hosts, as with storage servers used in a storage area network (SAN) environment. Still other storage servers are capable of servicing both file-level requests and block-level requests, as is the case with certain storage servers made by NetApp, Inc. of Sunnyvale, Calif.
A plurality of storage server nodes can be interconnected to provide a storage system environment configured to service many clients. Each storage server node can be configured to service one or more volumes, wherein each volume stores one or more logical containers of data (e.g., files, LUNs, etc.). Yet often a large number of data access requests issued by the clients are directed to a small number of such data containers serviced by a particular storage system of the environment. A solution to this problem is to distribute the volumes among all of the storage server nodes of the storage system environment. This, in turn, distributes the data access requests, along with the processing resources needed to service such requests, among all of the storage server nodes, thereby reducing the individual processing load on each node. However, a noted disadvantage arises when only a single data container, such as a file, is heavily accessed by clients of the storage system environment. As a result, the storage server node attempting to service the requests directed to that data container may exceed its processing resources and become overburdened, with a corresponding degradation of speed and performance.
One solution to this problem is to use a striped file system. A striped file system is a file system that includes multiple data volumes, where each file is distributed (“striped”) across multiple volumes. For any given file, some amount of data for the file (the first “stripe”, for example, the first 1 MB of data) is stored contiguously within one volume, then a different volume is chosen to store the next stripe of data, and yet another volume is responsible for the stripe after that, and so on.
A consumer of a file is made aware of this striping pattern, so that the appropriate volume can be consulted to perform read or write access against the desired stripe of the file. The striping pattern is often stored in a data structure called a “striping table”. A striping table is a data- or load-allocation data structure, which stores the pattern for striping data for a particular logical container of data (e.g., a file) across a plurality of storage resources (e.g., volumes). A particular striping table is made of multiple cells, where each cell corresponds to a different stripe of the logical data container and includes an identifier of the volume (or other storage resource) that contains that stripe. The table is considered infinitely repeating, so that if the desired stripe is beyond the end of the table, the “owner” volume for that stripe is given by the requested stripe modulo the number of cells in the table. Note that a striped file system typically hides the striping from the ultimate client, however, by embedding the knowledge of the striping pattern within a module that receives client requests and forwards them to an appropriate volume.
A particular striping table is tied to the number of constituent volumes (or other resources) making up the storage for the striped file system. For example, a striping table for storing data in a file system consisting of four volumes may not be suitable for a file system in which files are striped across three, five, or some other number of volumes.
Further, the particular layout of a striping table can affect the performance of a storage system. There are various performance related criteria on which one can judge the strength of a particular striping pattern (as represented in a striping table), such that some layouts of striped data may be preferable to others. One problem often encountered when generating a striping table, however, is that some of these criteria are mutually antagonistic, such that designing a striping pattern that is strong in one criterion might impair its performance in another criterion.
Another problem is associated with changes in the file system that increase or decrease the number of volumes across which data is striped. Because the striping table is tied to the number of volumes, the striping table needs to be modified when the geometry of the file system is changed in this way. Depending on the striping algorithm employed, adding or deleting even a single volume can necessitate modifying a significant portion of the striping table, which correspondingly implies having to migrate a large portion of the stored data to different volumes. Such data migration can be time-consuming and undesirably consumes computing resources and communications bandwidth.